mod app_config;
mod common_config;

use crate::config::cmd_arg::get_cmd_arg;
pub use app_config::*;
pub use common_config::*;
use etcd_manager_util::{global_config_manager, node_handler_manager};
use log_util::LogType;
use remote_log_util;
use std::process::exit;
use string_util::string_error::StringError;

pub type Result = std::result::Result<(), StringError>;

// 节点配置数据
pub const COMMON_CONFIG_NODE_PATH: &str = "/NFTServerConfig/LobbySeverConfig";
pub const APP_CONFIG_NODE_PATH: &str = "/NFTServerConfig/LobbySeverConfig/";

#[macro_export]
macro_rules! config_handler{
    {$config:ty}=>{
        pub(super) struct ConfigHandler();
        impl etcd_manager_util::common::NodeHandler for ConfigHandler{
            fn get_node_path(&self) -> String {
               <$config>::node_path()
            }

            // 获取加载权重,权重越高越优先加载
            fn get_load_weight(&self) -> u32 {
               <$config>::weight()
            }

            fn init_node(&self, change_type: etcd_manager_util::common::NodeChangeType, node_value: &etcd_manager_util::common::NodeValueModel) {
                super::log_result(<$config>::load(change_type,node_value),<$config>::node_path());
            }

            fn change_node(&self, change_type: etcd_manager_util::common::NodeChangeType, node_value: &etcd_manager_util::common::NodeValueModel) {
                super::log_result(<$config>::load(change_type,node_value),<$config>::node_path());
            }

            fn node_err(&self, err: &etcd_manager_util::EtcdError) {
                tokio::spawn( log_util::local_error!(format!(
                    "{} node error:{:?}",
                    self.get_node_path(),
                    err
                )));
            }
        }
        impl $config{
            pub fn get_handler()->Box<dyn etcd_manager_util::common::NodeHandler>{
                Box::new(ConfigHandler())
            }
        }
    }
}

// 加载用的扩展宏
macro_rules! load{
 ($loader:expr,$($instance:expr => $config:ty),*)=>(
      // 先注册到etcd manager
      $(node_handler_manager::register_node_handler(<$config>::get_handler()).await;)+
      // 执行相关初始化代码
      $loader;
      // 检查是否存在错误
      let mut is_have_error = false;
     $(
        {
            if $instance().is_error{
                log_util::write_log_print(true,LogType::Error,format!("{} load fail or not load", <$config>::module_name()),&None).await;
                is_have_error=true;
            }
         }
     )*
     // 如果存在错误，则直接退出
     if is_have_error{
          exit(1);
      }
    )
}

pub async fn load() {
    let load_fn = || async {
        let arg = get_cmd_arg();
        global_config_manager::pull_node_from_config_center(
            &arg.setting_server_addr,
            &format!("{}{}", APP_CONFIG_NODE_PATH, arg.app_node),
        )
        .await;
    };

    load!(load_fn().await
        ,app_config::get_app_config => app_config::AppConfig
        ,common_config::get_common_config => common_config::CommonConfig);
}

pub fn module_name() -> &'static str {
    "remoteConfig"
}

#[inline]
pub(super) fn log_result(result: Result, node_path: String) {
    match result {
        Ok(_) => return,
        Err(err) => {
            tokio::spawn(async move {
                remote_log_util::remote_error!(module_name(), err.to_string(), node_path).await
            });
        }
    }
}
